
#include "cmdp.h"
#include "Receivers.h"
#include "string.h"
#include "App.h"
#include "OS.h"
#include "debug.h"
#include "macros.h"
#include "Sys.h"
#include "dev.h"
#include "outf.h"
#include "VCom.h"
#include "sscanf.h"
#include "isd.h"
#include "storage.h"
#include "entrys.h"
#include "dev.h"
#include "memmap.h"
#include "SysClock.h"
#include "outp.h"

#define   CMD_BUF_SIZE	256

typedef void (*handler_t) (void);

typedef struct 
{
		char* cmd;
	   /* void (*cmd_handler) (void); */
	   handler_t cmd_handler;  
}cmd_handler_t;

typedef struct
{
		char buf[CMD_BUF_SIZE];
		int in_dev;
		int error;
}cmd_t;

cmd_t command;

char fixi_cmd[64];

static char *cmd_args;
//static char cmd_arg[24];

/* static char *cmd_get_arg ( void ) */
/* {	 */
/* 	if ( cmd_args == NULL ) */
/* 		return NULL; */

/* 	char *cp = NULL; */

/* 		while ( *cmd_args ) */
/* 	{ */
/* 		if ( *cmd_args++ == ' ' ) */
/* 		{ */
/* 			//return cmd_args; */
/* 			cp = cmd_args; */
/* 			break; */
/* 		} */
/* 	} */
	
/* 	if ( cp == NULL ) */
/* 		return NULL; */
	

/* 	return NULL; */
/* } */

static void cmd_handler_RS ( void )
{
	dbg(">>>>>>> RESET"); 
	Sys_Reset();
}

static void cmd_handler_IN ( void )
{
	outf(DEV_VCOM, "=M*A*I*N=");
	OS_Return();
}

static void cmd_handler_TEISD ( void )
{
#if 0	
	unsigned int addr, ctrl, a; //cmd;
	

	if ( (a=s_scanf(command.buf, "%*s %x %x", &addr, &ctrl)) == 2 )
	{
		DBG("\n%s; argsn: %d;  addr: 0x%04X; ctrl: 0x%04X\n",__FUNCTION__, a, addr, ctrl); 
		
/* 		cmd = addr; */
/* 		cmd |= ctrl<<11;  */
		
/* 		DBG("\n%s; isd_cmd: 0x%04X (0b%b)\n",__FUNCTION__, isd_cmd,isd_cmd);  */
		
		a = isd_cmd(addr, ctrl); 
		
		DBG("\n%s; isd_cmd() == 0x%X (0b%b)\n",__FUNCTION__, a,a); 
	}
	else
		command.error = CMD_ERR__WROND_ARGS_NUMBER;
#endif


	OS_Return();
}

extern int stext;
/* command for working with storage device (external eeprom) */
static void cmd_handler_PHONEL ( void )
{
//	#define DIR_INDEX(DIR_ADDR) (((unsigned int)DIR_ADDR-(unsigned int)&directories[0])/sizeof(storage_directory_properties_t))
/* 	outf(command.in_dev, "\nDIR_ADDR: %d; &directories[0]: %d", (const unsigned int)phone_add, &directories[0]);  */
/* 	outf(command.in_dev, "\nsizeof(storage_directory_properties_t): %d\n", sizeof(storage_directory_properties_t));  */
	
	int dir;
	char cmd[8], phone[64];
	
	int arg_count = s_scanf(command.buf, "%*s %s %d %s", cmd, &dir, phone);

	/* space cleaning */
	char *p = phone;

	while ( isdigit(*p) )p++;
	*p = 0; 


	DBG("\n%s; phone: '%s'\n",__FUNCTION__, phone); 

	if ( StrLen(phone) > 15 )
	{
		outf(DEV_ALL,"\n !!!phonel error: phone number [%s] is too long",phone);
		OS_Return();
	}	

	if (arg_count == 3 )
	{
		if ( !StrCmp(cmd, "add") )
		{
			command.error = storage.add(dir, phone);
		}
		else
			if ( !StrCmp(cmd, "delp") )
			{
				command.error = storage.delete_entry(dir, phone);
			}
	}
	else
		if ( arg_count == 2 )
		{
			if ( !StrCmp(cmd, "dell") )
			{
				command.error = storage.delete_directory(dir);
			}
			else
				if ( !StrCmp(cmd, "ls") )
				{
					storage.print(dir,command.in_dev);
				}
		}
		else
		{
			outf(command.in_dev,
				  "\n phonel add list# phone,\n phonel delp list# phone,\n phonel dell list#,\n phonel ls #list");
			command.error = CMD_ERR__WROND_ARGS_NUMBER;
		}
		

	OS_Return();
}

/* #define   DEV_PORT_A		1 */
/* #define   DEV_MODEM		2 */
/* #define   DEV_VCOM		3 */

static void cmd_handler_SEND ( void )
{
	int dev_number;
	char msg[256];

	int arg_count = s_scanf(command.buf, "%*s %d %s", &dev_number, msg);
	
	dbg("dev_number: %d",dev_number);
	dbg("message: %s",msg);
	
	
	if ( arg_count == 2 && dev_number >= DEV_PORT_A && dev_number <= DEV_VCOM )
	{
		outf(dev_number, "%s", msg);
	}
	else
	{
		outf(command.in_dev,"\nsend port \"string\"\n");
		outf(command.in_dev,"  ports:\n 1 - debug port\n 2 - modem port\n 3 - USB port\n");
	}
	
	OS_Return();
}

static void cmd_handler_PASSW1_SET_DEF ( void )
{
	unsigned char b = 0xFF;
	command.error = storage.Write(ADDR_PASSW_1, &b, 1); /* return amount of writed bytes */
	
	entrys_init();					  /* set default password1 */

	OS_Return();
}

static void cmd_handler_RESTORE_TO_DEFAULT ( void )
{
	char *m = NULL;
	unsigned char b = 0xFF;
	
	switch(APP.State)
	{
		case ASTE_START:
			OS_SET_TIMER(20000, ASTE_FINISH);
			DBG("\n%s; START \n\n\n",__FUNCTION__); //Dima	
			
			if ( command.in_dev == DEV_SMS )
			{
				APP.State = ASTE_FINISH;
				break;
			}

			outf(command.in_dev,"\n\t ===== SET TO DEFAULTS SETTINGS =====\n"); //Dima 
			outf(command.in_dev,"\n\t   ======= !!! WARNING !!! =======\n"); //Dima 
			outf(command.in_dev,"\n\t  All phones list will be deleted"); //Dima 
			outf(command.in_dev,"\n\t  Enter password will be set to defult"); //Dima 
			outf(command.in_dev,"\n\t  To continue type YES in other case send ENTER\n"); //Dima 
			APP.State = ASTE_WAIT_FOR_ENTER;
			break;

		case ASTE_WAIT_FOR_ENTER:
			if ( AuxPort_Message )
			{
				m = AuxPort_Message; 
			}
			else
				if ( VCom_Message )
				{
					m = VCom_Message;
				}

			if ( m )
			{
				if ( StrStr(m, "YES") )
				{
					APP.State = ASTE_RESET;
				}
				else
				{
					APP.State = ASTE_FINISH;
				}
			}
			break;

		case ASTE_RESET:
			storage.delete_directory(0);
			storage.delete_directory(1);
			storage.Write(ADDR_PASSW_1, &b, 1); /* return amount of writed bytes */
			entrys_init();					  /* set default password1 */
			command.error = 0;
			outf(command.in_dev, "\n\trestored to default\n");
			
		case ASTE_FINISH:
			DBG("\n%s; EXIT \n",__FUNCTION__); //Dima 
			OS_Return();
			break;

	}
}

static void cmd_handler_DBG ( void )
{
	g_debug ^=1;

	if (g_debug)
	{
		outf(command.in_dev, "\n\r DEBUG MODE: ON\n\r");
	}
	else
	{
		outf(command.in_dev, "\n\r DEBUG MODE: OFF\n\r");
	}

	OS_Return();
}

static void cmd_handler_TE ( void )
{
	outf(DEV_ALL, "\r\n =============== C15 ===============");
	//outf(DEV_ALL, "\r\n ====== MEC 4000 ===== v.%d.%d;  %d:%d:%d\n", VER,REV,day,month,year);
//	outf(DEV_ALL, "\r\n ====== MEC 4000 ===== v.%d.%d;  %s. %s\r\n", VER,REV,__DATE__,__TIME__);
	/* outf(DEV_ALL, "\r\n------ List of commands ----\r\n"); */
	/* outf(DEV_ALL, " RS - reset of device\r\n"); */
	/* outf(DEV_ALL, " phonel - command set of users lists\r\n"); */
	/* outf(DEV_ALL, " passw1_set_def - set delfault password 1\r\n"); */
	/* outf(DEV_ALL, " restore_def - set delfault settings\r\n"); */
	/* outf(DEV_ALL, " dbg - open/close debug log\r\n"); */
	/* outf(DEV_ALL, "\r\n---- End of list of commands ----\r\n"); */
	
	//DBG("\n%s; I'm live\n",__FUNCTION__); 
	OS_Return();
}





int fixi_mode;


const cmd_handler_t cmd_handlers[] = 
{
	{"IN", cmd_handler_IN},			  /* Information */
	{"RS", cmd_handler_RS},			  /* Restart for update */
	{"te", cmd_handler_TE},			  /* technical */
	{"dbg", cmd_handler_DBG},			  /* open debug */
	{"teisd", cmd_handler_TEISD},	  /* technical */
	{"phonel", cmd_handler_PHONEL},	  /* storage ST ADD; ST DEL; ST LS */
	{"SEND", cmd_handler_SEND},	  /* send to port (USB, Modem, PORT_A) */
	{"passw1_set_def", cmd_handler_PASSW1_SET_DEF},
	{"restore_def", cmd_handler_RESTORE_TO_DEFAULT},

	{NULL, NULL}
};


int cmd_add_command ( char *cmd, int Dev)
{
	if ( command.in_dev != 0 )
		return -1;
		
	StrCpy(command.buf, cmd);
	command.in_dev = Dev;
	command.error = 0;
	return 0;
}


void cmd_monitor ( void )
{
	if ( AuxPort_Message )
	{
		cmd_add_command(AuxPort_Message, DEV_PORT_A);
	}
	else
		if ( VCom_Message )
		{
			cmd_add_command(VCom_Message, DEV_VCOM);
		}
}

static handler_t cmd_find_cmd_mec(char *cmd)
{
	int i;
	char cmd_name[16];

	StrCpy_UpTo_Ch(cmd_name,cmd, ' ');
	
	for ( i=0; cmd_handlers[i].cmd != NULL; i++ )
	{
		if ( !StrCmp(cmd_name, cmd_handlers[i].cmd) )
		{
			return cmd_handlers[i].cmd_handler;
		}
	} 
 
	return NULL;
}




static handler_t cmd_find_cmd(char *cmd)
{
	handler_t handler;

	if ( (handler=cmd_find_cmd_mec(cmd)) != NULL )
	{
		return handler;
	}

	return NULL;
}


int cmd_index;

void cmd_processor ( void )
{
	handler_t handler;

	switch(APP.State)
	{
		case ASTE_START:
			DBG("\n%s; started\n",__FUNCTION__); 
			MemSet((unsigned char*)&command, sizeof(command), 0);
			cmd_args = command.buf;
			APP.State = ASTE_CHECK_FOR_COMMAND;
			break;
			
		case ASTE_CHECK_FOR_COMMAND:
			if ( command.in_dev )
			{
				dbg("===> command.buf: %s",command.buf);
				if ( (handler=cmd_find_cmd(command.buf)) != NULL )
				{
					APP.State = ASTE_WAIT_FOR_RESULT;
					OS_Call_App(0,handler);
				}
				else
				{
					DBG("\n\r%s; command not found\n\r",__FUNCTION__); 
					command.in_dev = 0;
				}
			}
			break; 	

		case ASTE_WAIT_FOR_RESULT:
			DBG("\n\r%s; in_dev: %d; cmd: %s; error: %d;",__FUNCTION__, command.in_dev,command.buf, command.error); 
			outf(command.in_dev,  "\nerror: %d\n\r", command.error);
			outf(command.in_dev,  "\rNX\r");
			outf(command.in_dev,  "\r\n");
			command.in_dev = 0;
			APP.State = ASTE_CHECK_FOR_COMMAND;
			break;
			
	}  
}
